﻿// ████

/**
 * 方块2的构造方法。
 * @return 方块2
 */
function Block2() {
    // 创建方块
    const block = new Block()

    // 初始化数据
    for (var j = 0; j < Const.BLOCK_GRID_COUNT_V; j++) {
        block.mBlocks[1][j].mUsed = true
    }

    // 初始化函数
    block.enterPreview = Block2_EnterPreview
    block.erase = Block2_Erase
    block.getBottom = Block2_GetBottom
    block.getTop = Block2_GetTop
    block.handleCannotMoveDown = Block2_HandleCannotMoveDown
    block.moveDown = Block2_MoveDown
    block.moveLeft = Block2_MoveLeft
    block.moveRight = Block2_MoveRight
    block.transform = Block2_Transform

    return block
}

/**
 * 进入预览区域。
 * @param block     方块2
 * @param drawer    绘图者
 */
function Block2_EnterPreview(block, drawer) {
    const x = Const.PREVIEW_WIDTH / 2 - Const.GRID_SIZE * 2
    const y = (Const.PREVIEW_HEIGHT - Const.GRID_SIZE) / 2

    for (var j = 0; j < Const.BLOCK_GRID_COUNT_H; j++) {
        drawer.fillStyle = block.mColor
        drawer.fillRect(x + Const.GRID_SIZE * j, y, Const.GRID_SIZE, Const.GRID_SIZE)
        Block.drawEdge(drawer, x + Const.GRID_SIZE * j, y)
    }
}

/**
 * 擦除。
 * @param block 方块2
 */
function Block2_Erase(block) {
    var x, y, width, height

    switch (block.mShape) {
        case Shape.ONE:
            x = Const.GRID_SIZE * block.mLine
            y = Const.GRID_SIZE * (block.mRow + 1)
            width = Const.GRID_SIZE * 4
            height = Const.GRID_SIZE
            break 
        case Shape.TWO:
            x = Const.GRID_SIZE * (block.mLine + 1)
            y = Const.GRID_SIZE * block.mRow
            width = Const.GRID_SIZE
            height = Const.GRID_SIZE * 4
            break 
    }
    block.eraseRect(block, x, y, width, height)
}

/**
 * 获取底端所在的行数。底端是指方块最下方的有效格。
 * @param block 方块2
 * @return 底端所在的行数
 */
function Block2_GetBottom(block) {
    if (block.mShape == Shape.ONE) {
        return block.mRow + 1
    }
    return block.mRow + 3
}

/**
 * 获取顶端所在的行数。顶端是指方块最上方的有效格。
 * @param block 方块2
 * @return 顶端所在的行数
 */
function Block2_GetTop(block) {
    if (block.mShape == Shape.ONE) {
        return block.mRow + 1
    }
    return block.mRow
}

/**
 * 对不能下落的处理。
 * @param block 方块2
 */
function Block2_HandleCannotMoveDown(block) {
    switch (block.mShape) {
        case Shape.ONE:
            for (var j = 0; j < Const.BLOCK_GRID_COUNT_H; j++) {
                gExistentBlocks[block.mRow + 1][block.mLine + j].mUsed = true
                gExistentBlocks[block.mRow + 1][block.mLine + j].mColor = block.mColor
            }
            break
        case Shape.TWO:
            for (var i = 0; i < Const.BLOCK_GRID_COUNT_V; i++) {
                gExistentBlocks[block.mRow + i][block.mLine + 1].mUsed = true
                gExistentBlocks[block.mRow + i][block.mLine + 1].mColor = block.mColor
            }
            break
    }
}

/**
 * 下落。
 * @param block 方块2
 * @return 成功则返回 true，否则返回 false
 */
function Block2_MoveDown(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mRow == 18) {
                block.handleCannotMoveDown(block)
                return false
            }
            for (var i = 0; i < Const.BLOCK_GRID_COUNT_H; i++) {
                if (gExistentBlocks[block.mRow + 2][block.mLine + i].mUsed) {
                    block.handleCannotMoveDown(block)
                    return false
                }
            }
            break
        case Shape.TWO:
            if (block.mRow == 16) {
                block.handleCannotMoveDown(block)
                return false
            }
            if (gExistentBlocks[block.mRow + 4][block.mLine + 1].mUsed) {
                block.handleCannotMoveDown(block)
                return false
            }
            break
    }
        
    return Block_MoveDown(block)
}

/**
 * 左移。
 * @param block 方块2
 */
function Block2_MoveLeft(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mLine == 0) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine - 1].mUsed) {
                return
            }
            break
        case Shape.TWO:
            if (block.mLine == -1) {
                return
            }
            for (var i = 0; i < Const.BLOCK_GRID_COUNT_V; i++) {
                if (gExistentBlocks[block.mRow + i][block.mLine].mUsed) {
                    return
                }
            }
            break
    }
    
    Block_MoveLeft(block)
}

/**
 * 右移。
 * @param block 方块2
 */
function Block2_MoveRight(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mLine == 6) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine + 4].mUsed) {
                return
            }
            break
        case Shape.TWO:
            if (block.mLine == 8) {
                return
            }
            for (var i = 0; i < Const.BLOCK_GRID_COUNT_V; i++) {
                if (gExistentBlocks[block.mRow + i][block.mLine + 2].mUsed) {
                    return
                }
            }
            break
    }

    Block_MoveRight(block)
}

/**
 * 变形。
 * @param block 方块2
 */
function Block2_Transform(block) {
    switch (block.mShape) {
        case Shape.ONE:
            if (block.mRow == -1 || block.mRow >= 17) {
                return
            }
            if (gExistentBlocks[block.mRow][block.mLine + 1].mUsed || 
                gExistentBlocks[block.mRow + 2][block.mLine + 1].mUsed || 
                gExistentBlocks[block.mRow + 3][block.mLine + 1].mUsed) {
                return
            }
            block.erase(block)
            block.mBlocks[1][0].mUsed = block.mBlocks[1][2].mUsed = block.mBlocks[1][3].mUsed = false
            block.mBlocks[0][1].mUsed = block.mBlocks[2][1].mUsed = block.mBlocks[3][1].mUsed = true
            block.mShape = Shape.TWO
            break
        case Shape.TWO:
            if (block.mLine == -1 || block.mLine >= 7) {
                return
            }
            if (gExistentBlocks[block.mRow + 1][block.mLine].mUsed || 
                gExistentBlocks[block.mRow + 1][block.mLine + 2].mUsed || 
                gExistentBlocks[block.mRow + 1][block.mLine + 3].mUsed) {
                return
            }
            block.erase(block)
            block.mBlocks[1][0].mUsed = block.mBlocks[1][2].mUsed = block.mBlocks[1][3].mUsed = true
            block.mBlocks[0][1].mUsed = block.mBlocks[2][1].mUsed = block.mBlocks[3][1].mUsed = false
            block.mShape = Shape.ONE
            break
    }
    
    block.draw(block)
}
